//
//  JJRnUpdateHelper.m
//  ClaimPlatform_RN
//
//  Created by woshiku on 2018/7/19.
//  Copyright © 2018年 jj. All rights reserved.
//

#import "JJRnUpdateHelper.h"
#import "JJBundleHelper.h"
#import "ADUtilHelper.h"
#import <ZipArchive.h>
#import "JJLog.h"
#import "JJ_ZGUtils.h"
static NSString *LOG_MODULENAME = @"JJRNUPDATE";

@implementation JJRnUpdateHelper

+(void)checkUpdate:(FinishBlock)finish{
    
    //finish(1,nil);
    NSString *url = @"init/queryRnHotUpdateInfo.do";
    NSString *localRnBundleVersion=[SNRNFileOperation getLocalRNBundleVersion];
    if ([localRnBundleVersion isEqualToString:@""]) {
        localRnBundleVersion=[JJommonTools snc_softwareVersion];
    }
    NSDictionary *param = @{@"mobile" : JJLoginInfo[@"mobile"],
                            @"rnBundleVersion" : localRnBundleVersion};
    
    [SNNetWorkManager postDataWithUrl:url parameters:param isEncryption:YES activityInView:nil success:^(id response) {
        
        if ([response[@"code"] isEqualToString:@"0000"]) {
            NSDictionary *data=response[@"data"];
            if (!JJ_IsNilOrNull(data)) {
                BOOL isUpdate=[[data objectForKey:@"isUpdate"]boolValue];
                if (isUpdate) {
                    //需要热更新
                    finish(1,response[@"data"]);
                }else{
                    //不需要热更新
                    finish(0,nil);
                }
            }else{
                finish(0,nil);
            }
        } else {
             finish(0,nil);
        }
       
    } failure:^(NSError *error) {
        finish(0,nil);
    }];
}

+(void)doRNHotUpdate{
    [SNRnUpdateHelper checkUpdate:^(NSInteger isUpdate, id data) {
        if (isUpdate) {
            
            NSString *appVersion=[JJommonTools snc_softwareVersion];
            //请求获取的唯一标识
            NSString *versionId=[data objectForKey:@"versionId"];
            //请求获取的热更新版本号
            NSString *rnBundleVersion=[data objectForKey:@"rnBundleVersion"];
            NSMutableDictionary *bundleDic=[NSMutableDictionary dictionaryWithObject:rnBundleVersion forKey:RNBUNDLEVERSIONKEY];
            if ([rnBundleVersion isEqualToString:appVersion]) {
                //如果 APPversion==应答RN bundle version
                //存储RN热更新信息
                [SNRNFileOperation storeFile:bundleDic fileName:[SNRNFileOperation getLocalRNBundleFile]];
                [self finishRnHotUpdate:versionId RnBundleVersion:rnBundleVersion IsSuccess:YES];
                JJLogInfo(LOG_MODULENAME, @"appversion: %@, rnBundleVersion: %@", appVersion,rnBundleVersion);
            }else{
               
                //请求获取Rn热更新文件加密的MD5值
                NSString *bundleFileMd5=[[data objectForKey:@"bundleFileMd5"]uppercaseString];
                //请求获取的下载地址
                NSString *downloadUrl=[data objectForKey:@"downloadUrl"];
                
                //获取对应RNbundleVersion信息，存储的本地Rnbundle包文件
                NSString *rnBundleVersionFolder=[NSString stringWithFormat:@"%@/\%@%@",[SNRNFileOperation getBundleFloderPath],RNBUNDLEFLODERPRE,rnBundleVersion];
                BOOL rnBundleFileisExit=[SNRNFileOperation localFileIsExit:rnBundleVersionFolder];
                if (rnBundleFileisExit) {
                    JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,rnBundleFile Exit", rnBundleVersion);
                    //存在本地的Rn bundle
                    NSString *localJsMainBundlePath=[NSString stringWithFormat:@"%@/\%@",rnBundleVersionFolder,MAIN_JSBUNDLE];
                    //对应版本的bundle的MD5值
                    NSString *bundleFileMD5=[[ADUtilHelper getFileMD5WithPath:localJsMainBundlePath]uppercaseString];
                    //本地存储的bundle对应的MD5值
                    NSString *localStoreMD5=[SNRNFileOperation getRNBundleMD5Value:rnBundleVersion];
                    if ([bundleFileMD5 isEqualToString:localStoreMD5]) {
                        //MD5验证成功
                        //存储RN热更新信息
                        [SNRNFileOperation storeFile:bundleDic fileName:[SNRNFileOperation getLocalRNBundleFile]];
                        [self finishRnHotUpdate:versionId RnBundleVersion:rnBundleVersion IsSuccess:YES];
                        JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,bundleFileMD5: %@,is equal localStoreMD5: %@", rnBundleVersion,bundleFileMD5,localStoreMD5);
                    }else{
                        //MD5验证不成功
                        //删除本地对应版本的RN bundle
                        JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,bundleFileMD5: %@,is not equal localStoreMD5: %@", rnBundleVersion,bundleFileMD5,localStoreMD5);
                        [SNRNFileOperation deleteLocalFile:rnBundleVersionFolder];
                        [self downLoadRnBundleFile:downloadUrl BundleFileMD5:bundleFileMd5 RnBundleVersion:rnBundleVersion Finish:^(BOOL isSame) {
                            if (isSame) {
                                
                            }else{
                                //清空临时目录
                                [SNRNFileOperation deleteLocalFile:[SNRNFileOperation getRnBundleTempPath]];
                                [self finishRnHotUpdate:versionId RnBundleVersion:rnBundleVersion IsSuccess:NO];
                            }
                        }];
                     }
                }else{
                       //不存在本地对应的RNbundle包
                    JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,rnBundleFile is not Exited", rnBundleVersion);
                    [self downLoadRnBundleFile:downloadUrl BundleFileMD5:bundleFileMd5 RnBundleVersion:rnBundleVersion Finish:^(BOOL isSame) {
                           if (isSame) {
                               //清空临时目录
                             [SNRNFileOperation deleteLocalFile:[SNRNFileOperation getRnBundleTempPath]];
                             //存储RNbundle对应的MD5值到本地
                             [SNRNFileOperation storeRNBundleMD5ToFile:rnBundleVersion MD5:bundleFileMd5];
                             //存储RN热更新信息
                             [SNRNFileOperation storeFile:bundleDic fileName:[SNRNFileOperation getLocalRNBundleFile]];
                             [self finishRnHotUpdate:versionId RnBundleVersion:rnBundleVersion IsSuccess:YES];
                           }else{
                            //清空临时目录
                             [SNRNFileOperation deleteLocalFile:[SNRNFileOperation getRnBundleTempPath]];
                            [self finishRnHotUpdate:versionId RnBundleVersion:rnBundleVersion IsSuccess:NO];
                           }
                       }];
                }
                
                
            }
            
        }else{
            //不需要热更新 结束；
        }
    }];
}

+(void)downLoadRnBundleFile:(NSString*)downLoadUrl BundleFileMD5:(NSString*)bundleFileMd5 RnBundleVersion:(NSString*)rnBundleVersion Finish:(BundleFileMD5CheckBlock)finish{
    //下载之前先清空临时目录
    [SNRNFileOperation deleteLocalFile:[SNRNFileOperation getRnBundleTempPath]];
    //下载新的bundle包
    [[SNFileHelper shared]downloadFileWithURLString:downLoadUrl finish:^(NSInteger status, id data) {
        if (status) {
            //下载成功了
            JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file download success", rnBundleVersion);
            NSString *rnBundleZipPath=(NSString*)data;
            
            ZipArchive *zip = [[ZipArchive alloc] init];
            if( [zip UnzipOpenFile:rnBundleZipPath]){
                NSArray *fileContents=[zip getZipFileContents];
                if ([self verifyZipFileCompleteness:fileContents]) {
                    NSString *unzipDownFolderPath=[NSString stringWithFormat:@"%@/\%@%@",[SNRNFileOperation getRnBundleTempPath],RNBUNDLEFLODERPRE,rnBundleVersion];
                    BOOL result = [zip UnzipFileTo:[SNRNFileOperation getRnBundleTempPath] overWrite:YES];
                    if(result){
                        //解压成功了
                        JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file unZip success", rnBundleVersion);
                        NSString *unZipDownMainBundlePath=[NSString stringWithFormat:@"%@/\%@",unzipDownFolderPath,MAIN_JSBUNDLE];
                        NSString *downBundleMD5=[[ADUtilHelper getFileMD5WithPath:unZipDownMainBundlePath]uppercaseString];
                        if ([bundleFileMd5 isEqualToString:downBundleMD5]) {
                            JJLogInfo(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file MD5 checked is same", rnBundleVersion);
                            //MD5值一致
                            /* BOOL isMove=[SNRNFileOperation moveFile:unzipDownFolderPath DestiFile:[SNRNFileOperation getBundleFloderPath]];*/
                            BOOL isMove = [zip UnzipFileTo:[SNRNFileOperation getBundleFloderPath] overWrite:YES];
                            if(isMove){
                                //移动成功
                                [self doZhugeTrackForRnUpdate:@"RN热更新-下载成功" DownLoadUrl:downLoadUrl UpdateVersion:rnBundleVersion FailReason:nil];
                                finish(YES);
                            }else{
                                //移动失败
                                [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"移动失败"];
                                finish(NO);
                            }
                            
                        }else{
                            //MD5值不一致
                            JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file MD5 checked is not same", rnBundleVersion);
                            [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"MD5校验失败"];
                            finish(NO);
                        }
                    }else{
                        //解压失败了
                        JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file unZip fail", rnBundleVersion);
                        [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"解压失败"];
                        finish(NO);
                    }
                }else{
                    //存在漏洞
                    JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file exit leak", rnBundleVersion);
                    [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"存在漏洞"];
                    finish(NO);
                }
            }else{
                //解压失败了
                JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file unZip fail", rnBundleVersion);
                [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"解压失败"];
                finish(NO);
            }
        }else{
            //下载失败了，清空临时目录
            JJLogWarn(LOG_MODULENAME, @"rnBundleVersion: %@,RNbundle file download fail", rnBundleVersion);
            [self doZhugeTrackForRnUpdate:@"RN热更新-下载失败" DownLoadUrl:downLoadUrl UpdateVersion:nil FailReason:@"下载失败"];
            finish(NO);
        }
    }];
}

+(void)finishRnHotUpdate:(NSString*)versionID RnBundleVersion:(NSString*)rnBundleVersion IsSuccess:(BOOL)isSuccess{
    NSString *url = @"init/finishRnHotUpdate.do";
    NSString *successStr=@"0";
    if(isSuccess){
        successStr=@"1";
    }
    NSDictionary *param = @{@"isSuccess" : successStr,
                            @"rnBundleVersion" : rnBundleVersion,
                            @"versionId" : versionID
                            };
    
    [SNNetWorkManager postDataWithUrl:url parameters:param isEncryption:NO activityInView:nil success:^(id response) {
        //无需处理请求结果
        if ([response[@"code"] isEqualToString:@"0000"]) {
          
        } else {
            
        }
        
    } failure:^(NSError *error) {
        NSLog(@"WWWWWW");
    }];
}
/*+(BOOL)verifyZipFileCompleteness:(NSString*)filePath{
    ZipArchive *zip = [[ZipArchive alloc] init];
    
    if( [zip UnzipOpenFile:filePath]){
        NSArray *fileContents=[zip getZipFileContents];
        for (NSString *fileName in fileContents) {
            if ([fileName rangeOfString:@"../"].location != NSNotFound) {
                return NO;
            }
        }
    }
    return YES;
}*/
//检验解压的文件是否存在漏洞
+(BOOL)verifyZipFileCompleteness:(NSArray*)arrayfiles{
    for (NSString *fileName in arrayfiles) {
        if ([fileName rangeOfString:@"../"].location != NSNotFound) {
          return NO;
        }
    }
    return YES;
}
//Rn热更新下载埋点
+(void)doZhugeTrackForRnUpdate:(NSString*)eventName DownLoadUrl:(NSString*)downLoadUrl UpdateVersion:(NSString*)updateVersion FailReason:(NSString*)failReason{
    NSMutableDictionary *dic = [NSMutableDictionary dictionary];
    if (!JJ_IsStrEmpty(downLoadUrl)){
        dic[@"下载地址"] = downLoadUrl;
    }
    if (!JJ_IsStrEmpty(updateVersion)){
        dic[@"更新版本"] = updateVersion;
    }
    if (!JJ_IsStrEmpty(failReason)){
        dic[@"原因"] = failReason;
    }
    [JJ_ZGUtils zhugeTrackWithName:eventName info:dic];
}

@end
